package com.appwithheart.toolkit;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;

import android.os.FileObserver;
import android.util.Log;


public abstract class FileTreeObserver extends FileObserver{

	
	public static final int STATE_MONITORING = 100;
	public static final int STATE_NOT_MONITORING = 200;
	
	private static String TAG = FileTreeObserver.class.getSimpleName();
	private static boolean isSendLog = true;
	
	
	private FileNodeObserver rootNode;
	private HashMap<String, FileNodeObserver> observerMap = new HashMap<String, FileNodeObserver>();
	public HashMap<String, FileNodeObserver> getObserverMap() {
		return observerMap;
	}



	private int state;

	
	private static int defaultMask = 
		FileObserver.CREATE +
		FileObserver.DELETE + 
		FileObserver.DELETE_SELF +
		FileObserver.MOVE_SELF + 
		FileObserver.MOVED_FROM +
		FileObserver.MOVED_TO;
	
	private static Hashtable<Integer, String> eventStringTable;
	
	static{
		
		eventStringTable = new Hashtable<Integer, String>();
		
		//All events
		eventStringTable.put(FileObserver.ACCESS, "ACCESS");
		eventStringTable.put(FileObserver.ATTRIB, "ATTRIB");
		eventStringTable.put(FileObserver.CLOSE_NOWRITE, "CLOSE_NOWRITE");
		eventStringTable.put(FileObserver.CLOSE_WRITE, "CLOSE_WRITE");
		eventStringTable.put(FileObserver.CREATE, "CREATE");
		eventStringTable.put(FileObserver.DELETE, "DELETE");
		eventStringTable.put(FileObserver.DELETE_SELF, "DELETE_SELF");
		eventStringTable.put(FileObserver.MODIFY, "MODIFY");
		eventStringTable.put(FileObserver.MOVE_SELF, "MOVE_SELF");
		eventStringTable.put(FileObserver.MOVED_FROM, "MOVED_FROM");
		eventStringTable.put(FileObserver.MOVED_TO, "MOVED_TO");
		eventStringTable.put(FileObserver.OPEN, "OPEN");
		
	}
	
	public FileTreeObserver(String path) throws IOException {
		super(path);
		
		File file = new File(path);
		
		if(!file.exists())
			throw new FileNotFoundException();
			
		rootNode = new FileNodeObserver(this, path){

			@Override
			public void onNodeEvent(int event, String absolutePath) {
				//Do nothing
			}
		};
		
		state = STATE_NOT_MONITORING;
	}
	
	/**
	 * 
	 * For recursively usage, some mask will be added by default.
	 * 
	 * Those default mask values will be ignored if pass into constructor.
	 * 
	 * 
	 * @param path
	 * @param mask
	 * @throws IOException 
	 */
	
	public FileTreeObserver(String path, int mask) throws IOException {
		super(path, mask);
		
		File file = new File(path);
		
		if(!file.exists())
			throw new FileNotFoundException();
	
		int filteredMask = 0;
		
		//To filter out the mask value which are not in default masks
		filteredMask = mask & ~defaultMask;
		
		if(isSendLog){
			Log.d(TAG, "Filtered masks = "+filteredMask);
		}
		
		rootNode = new FileNodeObserver(this, path, defaultMask + filteredMask){

			@Override
			public void onNodeEvent(int event, String absolutePath) {
				//Do nothing
			}
		};
		
		state = STATE_NOT_MONITORING;
	}

	
	public synchronized int getState() {
		return state;
	}

	@Override
	public synchronized void startWatching(){
		rootNode.addObservers();
		
		state = STATE_MONITORING;
	}
	
	@Override
	public synchronized void stopWatching(){
		rootNode.removeObservers();
		
		state = STATE_NOT_MONITORING;
	}
	

	
	public static String getEventString(int eventId){
		
		return eventStringTable.get(eventId);
	}
	
}
